#ifndef PERSPECTIVECAMERA_H
#define PERSPECTIVECAMERA_H

#include "Renderer/camera.h"
#include <glm/glm.hpp>
#include "Core/base.h"

namespace CC
{

    class CC_EXPORT PerspectiveCamera : public Camera
    {
    public:
        PerspectiveCamera(const glm::mat4 projection);
        PerspectiveCamera(float fovy, float aspect, float zNear, float zFar);
        ~PerspectiveCamera();

        void OnUpdate(Timestep ts);
        void OnEvent(Event &e);

        void SetProjection(float fovy, float aspect, float zNear, float zFar);

        glm::vec3& GetPosition() { return m_Position; }
        float* GetPositionPointer() { return &m_Position[0]; }
        void SetPosition(const glm::vec3 position)
        {
            m_Position = position;
            RecalculateViewMatrix();
        }

        glm::vec3 GetTargetPosition() const { return m_TargetPosition; }
        void SetTargetPosition(const glm::vec3 position)
        {
            m_TargetPosition = position;
            RecalculateViewMatrix();
        }

        float GetRotation() const { return m_Rotation; }
        void SetRotation(float rotation)
        {
            m_Rotation = rotation;
            RecalculateViewMatrix();
        }

        float& GetRotationYaw() { return m_Yaw; }
        float* GetRotationYawPointer() { return &m_Yaw; }
        void SetRotationYaw(float rotation)
        {            
            m_Yaw = rotation;
            RecalculateViewMatrix();
        }

        float& GetRotationPitch() { return m_Pitch; }
        float* GetRotationPitchPointer() { return &m_Pitch; }
        void SetRotationPitch(float rotation)
        {
            //if (abs(rotation) >= 50) return;
            m_Pitch= rotation;
            RecalculateViewMatrix();
        }

        glm::vec3 GetUpAxis() const { return m_Up; }

        const glm::mat4 &GetViewMatrix() const { return m_ViewMatrix; }
        const glm::mat4 &GetViewProjectionMatrix() const { return m_ViewProjectionMatrix; }

        float GetAspect() { return m_aspect; }
        void SetAspect(float a);

        float GetFovy() { return m_fovy; }
        float GetFovyRadian() { return glm::radians(m_fovy); }

        void SetHasLookAt(bool r) { m_HasLookAt = r; }
        bool GetHasLookAt() { return m_HasLookAt; }

    private:
        void RecalculateViewMatrix();
        void OnWindowResize(WindowResizeEvent &e);

    private:
        glm::mat4 m_ViewMatrix;
        glm::mat4 m_ViewProjectionMatrix;

        glm::vec3 m_Position = {0.0f, 0.0f, 0.0f};
        glm::vec3 m_TargetPosition = {0.0f, 0.0f, 0.0f};
        float m_Rotation = 0.0f;
        float m_fovy;
        float m_aspect;
        float m_zNear;
        float m_zFar;

        glm::vec3 m_Front;
        glm::vec3 m_Up;
        glm::vec3 m_Right;
        glm::vec3 m_WorldUp;

        // euler Angles
        float m_Yaw;   // 偏航 270.0f -z
        float m_Pitch; // 俯仰

        bool m_HasLookAt = false;
    };

}
#endif